﻿
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PetGo
{
    /// <summary>
    /// color of fields on the board
    /// </summary>
    enum color
    {
        black = 1,
        white = -1,
        empty = 0
    }
    /// <summary>
    /// represents all groups on the board
    /// </summary>
    class Group
    {
        public int myposition;
        //public int myboardsize;
        public Dictionary<int, int> myFields;
        public Dictionary<int, int> myEyes;
        public Dictionary<int, int> myNeighbors;
        public Dictionary<int, int> myLibs;
        public Dictionary<int, int> mypotEye;

        public int alive;
        public int dead;
        public double alivestat;
        public color myColor;

        public static Dictionary<int, int> eyecandidates = new Dictionary<int, int>();
        public static Dictionary<int, Dictionary<int, int>> myNeighborCach = new Dictionary<int, Dictionary<int, int>>();
        public static Dictionary<int, Dictionary<int, int>> myRadCache = new Dictionary<int, Dictionary<int, int>>();
        public static Dictionary<int, int> fullLib = new Dictionary<int, int>();

        public static int groupLenght = 0; 
        /// <summary>
        /// creates new empty group on the board
        /// </summary>
        /// <param name="position"></param>
        /// <param name="boardsize"></param>
        public Group(int position, int boardsize, color color, Board board)
        {
            //myboardsize = boardsize;
            myColor = color;
            myposition = position;
            myFields = new Dictionary<int, int>();
            myNeighbors = new Dictionary<int, int>();
            myEyes = new Dictionary<int, int>();
            myLibs = new Dictionary<int, int>();
            mypotEye = new Dictionary<int, int>();
            addField(myposition, board, true);
            // check, can be
            //if (myLibs.Count == 0)
            //{
            //    ;
            //}
        }

        /// <summary>
        /// adds a field to this group
        /// </summary>
        /// <param name="theposition"></param>
        public void addField(int theposition, Board board, bool quick)
        {

            myFields[theposition] = theposition;
            if (!quick && myNeighbors.ContainsKey(theposition))
            {
                myNeighbors.Remove(theposition);
                myLibs.Remove(theposition);
                mypotEye.Remove(theposition);
            }

            addNeighbors(theposition, board, quick);
            //foreach (int i in myFields.Keys)
            //{
            //    board.myGroupPosition[i] = this.myposition;
            //}
            board.myGroupPosition[theposition] = this.myposition;
        }

        /// <summary>
        /// merges the given group into this group
        /// </summary>
        /// <param name="theGroup">the group to be merged (and disposed)</param>
        /// <param name="theBoard">the board on with the groups are</param>
        public void merge(Group theGroup, Board theBoard)
        {
           
            //foreach (int pos in theGroup.myFields.Keys)
            //{
            //    addField(pos, theBoard);
            //}
            foreach (int pos in theGroup.myNeighbors.Keys)
            {
                myNeighbors[pos] = pos;
            }

            foreach (int pos in theGroup.myLibs.Keys)
            {
                myLibs[pos] = pos;
            }
            foreach (int pos in theGroup.mypotEye.Keys)
            {
                mypotEye[pos] = pos;
            }
            foreach (int pos in theGroup.myFields.Keys)
            {
                myFields[pos] = pos;
                theBoard.myGroupPosition[pos] = myposition;
            }
            foreach (int pos in theGroup.myEyes.Keys)
            {
                myEyes[pos] = pos;
            }
            
            // to ensure eyedetection:
            //foreach (int pos in myFields.Keys)
            //{
            //    addField(pos, theBoard);
            //}
            theGroup.dispose(theBoard);
        }


        /// <summary>
        /// adds all neighbors of position to group
        /// </summary>
        /// <param name="boardsize"></param>
        /// <param name="position"></param>
        public void addNeighbors(int position, Board board, bool quick)
        {
            if (myFields.Count == 1)
            {
                myNeighbors = new Dictionary<int, int>(getNeighbors(position, board.myboardsize));
            }
            //if (quick)
            //{
            //    foreach (int neighbor in getNeighbors(position, board.myboardsize).Keys)
            //    {
            //        if (!board.myGroupPosition.ContainsKey(neighbor))
            //        {
            //            myLibs[neighbor] = neighbor;
            //        }
            //    }
            //}
            //else
            //{
                foreach (int neighbor in getNeighbors(position, board.myboardsize).Keys)
                {
                    if (quick || !myFields.ContainsKey(neighbor))
                    {
                        //if (!myNeighbors.ContainsKey(neighbor))
                        //{
                        myNeighbors[neighbor] = neighbor;
                        if (!board.myGroupPosition.ContainsKey(neighbor))
                        {
                            myLibs[neighbor] = neighbor;
                            bool ispoteye = true;
                            List<int> potgr = new List<int>();
                            foreach (int n in getNeighbors(neighbor, board.myboardsize).Keys)
                            {
                                if (n == position) continue;
                                if (!board.myGroupPosition.ContainsKey(n) || board.myGroup[board.myGroupPosition[n]].myColor != myColor)
                                {
                                    ispoteye = false;
                                    break;
                                }
                                else
                                {
                                    if (!potgr.Contains(board.myGroupPosition[n]))
                                    {
                                        potgr.Add(board.myGroupPosition[n]);
                                    }
                                }
                            }
                            if (ispoteye)
                            {
                                foreach (int g in potgr)
                                {
                                    board.myGroup[g].mypotEye[neighbor] = neighbor;
                                }
                                mypotEye[neighbor] = neighbor;
                            }
                        }
                        //}
                    }
                }
        }
        //}

        /// <summary>
        /// Copies the Group
        /// </summary>
        /// <returns></returns>
        public Group Copy(Board board)
        {
            Group theReturn = new Group(myposition, board.myboardsize, myColor, board);
            theReturn.myFields = DictCopy(myFields);
            theReturn.myEyes = DictCopy(myEyes);
            theReturn.myLibs = DictCopy(myLibs);
            theReturn.mypotEye = DictCopy(mypotEye);
            theReturn.myNeighbors = DictCopy(myNeighbors);
            theReturn.alive = alive;
            theReturn.dead = dead;
            return theReturn;
        }

        /// <summary>
        /// Copies a Dict <int, int>
        /// </summary>
        /// <param name="theDictToCopy"></param>
        /// <returns></returns>
        static public Dictionary<int, int> DictCopy(Dictionary<int, int> theDictToCopy)
        {
            Dictionary<int, int> theReturn = new Dictionary<int, int>(theDictToCopy);
            //foreach (int x in theDictToCopy.Keys)
            //{
            //    theReturn[x] = theDictToCopy[x];
            //}
            return theReturn;
        }

        private void dispose(Board theBoard)
        {
            myFields.Clear();
            myEyes.Clear();
            //myNeighbors.Clear();
            theBoard.myGroup.Remove(myposition);
        }
        public static Dictionary<int, int> getNeighbors_rad_no_cache(int position, Board theBoard, int radius)
        {
            int boardsize = theBoard.myboardsize;
            int key = radius * boardsize * boardsize + position;
            Dictionary<int, int> Return = new Dictionary<int, int>();
            for (int x = -Math.Min(radius, position % boardsize); x <= Math.Min(radius, boardsize - position % boardsize - 1); ++x)
            {
                for (int y = -Math.Min(radius, position / boardsize); y <= Math.Min(radius, boardsize - position / boardsize - 1); ++y)
                {
                    if (x == 0 && y == 0) continue;
                    if (theBoard.myGroupPosition.ContainsKey(position + x + y * boardsize))
                    {
                        Return[position + x + y * boardsize] = theBoard.myGroupPosition[position + x + y * boardsize];
                    }
                }
            }
            return Return;
        }
       
        public static Dictionary<int, int> getNeighbors_rad(int position, Board theBoard, int radius)
        {
            int boardsize = theBoard.myboardsize;
            int key = radius * boardsize * boardsize + position;
            if (myRadCache.ContainsKey(key)) return myRadCache[key];

            Dictionary<int, int> Return = getNeighbors_rad_no_cache(position, theBoard, radius);
            myRadCache[key] = Return;
            return Return;
        }

        public static Dictionary<int, int> getNeighbors_Fields_rad(int position, Board theBoard, int radius)
        {
            int boardsize = theBoard.myboardsize;
            Dictionary<int, int> Return = new Dictionary<int, int>();
            for (int x = -Math.Min(radius, position % boardsize); x <= Math.Min(radius, boardsize - position % boardsize - 1); ++x)
            {
                for (int y = -Math.Min(radius, position / boardsize); y <= Math.Min(radius, boardsize - position / boardsize - 1); ++y)
                {
                    if (x == 0 && y == 0) continue;
                    if (!theBoard.myGroupPosition.ContainsKey(position + x + y * boardsize))
                    {
                        Return[position + x + y * boardsize] = position + x + y * boardsize;
                    }
                }
            }
            return Return;
        }


        static public Dictionary<int, int> getNeighbors(int position, int boardsize)
        {
            //if (myNeighborCach.Count > boardsize*boardsize)
            //{
            //    myNeighborCach.Clear();
            //}
            if (myNeighborCach.ContainsKey(position)) return myNeighborCach[position];

            // later Cash this with new class
            Dictionary<int, int> Neighbors = new Dictionary<int, int>();
            // unless right border
            if (position % boardsize != boardsize - 1)
            {
                Neighbors[position + 1] = position + 1;
            }
            // unless lower border
            if (position / boardsize != boardsize - 1)
            {
                Neighbors[position + boardsize] = position + boardsize;
            }
            // unless upper border
            if (position / boardsize != 0)
            {
                Neighbors[position - boardsize] = position - boardsize;
            }
            // unless left border
            if (position % boardsize != 0)
            {
                Neighbors[position - 1] = position - 1;
            }
            myNeighborCach[position] = Neighbors;
            return Neighbors;
        }
        internal void killed_new(Board board)
        {
            //foreach (int nei in myNeighbors.Keys)
            //{
            //    if (board.myGroupPosition.ContainsKey(nei))
            //    {
            //        foreach(int opnei in board.myGroup[board.myGroupPosition[nei]].myNeighbors.Keys)
            //        {
            //            if (myFields.ContainsKey(opnei))
            //            {
            //                board.myGroup[board.myGroupPosition[nei]].myLibs[opnei] = opnei;
            //            }
            //        }
            //    }
            //}
            List<int> neiGroup = new List<int>();

            foreach (int i in myFields.Keys)
            {
                foreach (int nei in Group.getNeighbors(i, board.myboardsize).Keys)
                {
                    if (board.myGroupPosition.ContainsKey(nei) && board.myGroup[board.myGroupPosition[nei]].myposition != myposition)
                    {
                        foreach (int j in Group.getNeighbors(nei, board.myboardsize).Keys)
                        {
                            if (board.getdistance_int(i, j) > 2)
                            {
                                continue;
                            }
                            if (!board.myGroupPosition.ContainsKey(j) && !board.myGroup[board.myGroupPosition[nei]].myEyes.ContainsKey(j))
                            {
                                if (!neiGroup.Contains(j))
                                {
                                    neiGroup.Add(j);
                                }
                            }
                        }
                        board.myGroup[board.myGroupPosition[nei]].myLibs[i] = i;
                        if (myFields.Count == 1)
                        {
                            board.myGroup[board.myGroupPosition[nei]].mypotEye[i] = i;
                        }

                    }
                }
                board.myGroupPosition.Remove(i);
                board.myEmptyFields[i] = i;
            }
            foreach (int g in neiGroup)
            {
                if (board.ispotentialeye(g))
                {
                    foreach (int nei in Group.getNeighbors(g, board.myboardsize).Keys)
                    {
                        if (!board.myGroup[board.myGroupPosition[nei]].myEyes.ContainsKey(g) && !board.myGroup[board.myGroupPosition[nei]].mypotEye.ContainsKey(g))
                        {
                            board.myGroup[board.myGroupPosition[nei]].mypotEye[g] = g;
                            //++Board.randmovescount;
                        }
                    }
                }
            }
            dispose(board);
            Board.movesb.Clear();
            Board.movesw.Clear();
        }
        /// <summary>
        /// kills this group
        /// </summary>
        /// <param name="board">on this board</param>
        internal void killed(Board board)
        {
            //foreach (int nei in myNeighbors.Keys)
            //{
            //    if (board.myGroupPosition.ContainsKey(nei))
            //    {
            //        foreach(int opnei in board.myGroup[board.myGroupPosition[nei]].myNeighbors.Keys)
            //        {
            //            if (myFields.ContainsKey(opnei))
            //            {
            //                board.myGroup[board.myGroupPosition[nei]].myLibs[opnei] = opnei;
            //            }
            //        }
            //    }
            //}
            foreach (int i in myFields.Keys)
            {
                foreach (int nei in Group.getNeighbors(i, board.myboardsize).Keys)
                {
                    if (board.myGroupPosition.ContainsKey(nei) && board.myGroup[board.myGroupPosition[nei]].myposition != myposition)
                    {
                        board.myGroup[board.myGroupPosition[nei]].myLibs[i] = i;
                        if (myFields.Count == 1)
                        {
                            board.myGroup[board.myGroupPosition[nei]].mypotEye[i] = i;
                        }
                        
                    }
                }
                board.myGroupPosition.Remove(i);
                board.myEmptyFields[i] = i;
            }
            dispose(board);
            Board.movesb.Clear();
            Board.movesw.Clear();
        }
        /// <summary>
        /// counts liberties of the group
        /// </summary>
        /// <returns>count of liberties</returns>
        internal int getLibertyCount(Board theBoard)
        {
            return myLibs.Count;
        }
        /// <summary>
        /// counts liberties of the group
        /// </summary>
        /// <returns>count of liberties</returns>
        //internal int getLibertyCountNoCache(Board theBoard)
        //{
        //    int theReturn = 0;
        //    foreach (int pos in myNeighbors.Keys)
        //    {
        //        if (!theBoard.myGroupPosition.ContainsKey(pos)) ++theReturn;
        //    }
        //    return theReturn;
        //}
        public static int getLibertyCount(int thepos, Board theBoard)
        {
            int theReturn = 0;
            foreach (int pos in getNeighbors(thepos, theBoard.myboardsize).Keys)
            {
                if (!theBoard.myGroupPosition.ContainsKey(pos)) ++theReturn;
            }
            return theReturn;
        }

        public static int getLibertyCount_full(int thepos, Board theBoard, int morethan)
        {
            groupLenght = 0;
            //if (Tree.myRootBoard.mytoMove == color.black)
            //{
            //    return getLibertyCount(thepos, theBoard);
            //}
            int killedOpp = -1;
            fullLib.Clear();
            //List<int> theLibs = new List<int>();
            foreach (int pos in getNeighbors(thepos, theBoard.myboardsize).Keys)
            {
                if (!theBoard.myGroupPosition.ContainsKey(pos))
                {
                    if (!fullLib.ContainsKey(pos)) fullLib[pos] = pos;
                    if (fullLib.Count > morethan) break;
                }
                else
                {
                    Group cGroup = theBoard.myGroup[theBoard.myGroupPosition[pos]];
                    if (cGroup.myColor == theBoard.mytoMove)
                    {
                        groupLenght += cGroup.myFields.Count;
                        if (cGroup.myLibs.Count - 1 > morethan) return morethan + 1;
                        if (cGroup.myEyes.Count > 1) return 99;
                        foreach (int l in cGroup.myLibs.Keys)
                        {
                            if (l != thepos && !fullLib.ContainsKey(l)) fullLib[l] = l;
                            if (fullLib.Count > morethan) break;
                        }
                    }
                    else
                    {
                        if (cGroup.myLibs.Count == 1)
                        {
                            if (!fullLib.ContainsKey(pos)) fullLib[pos] = pos;
                            if (cGroup.myFields.Count > 1) killedOpp = cGroup.myposition;
                            if (fullLib.Count > morethan) break;
                        }
                    }
                }
            }
            if (killedOpp > -1 && fullLib.Count <= morethan)
            {
                foreach (int pos in getNeighbors(thepos, theBoard.myboardsize).Keys)
                {
                    if (!theBoard.myGroupPosition.ContainsKey(pos)) continue;
                    Group cGroup = theBoard.myGroup[theBoard.myGroupPosition[pos]];
                    if (cGroup.myColor == theBoard.mytoMove)
                    {
                        foreach(int cField in theBoard.myGroup[killedOpp].myFields.Keys)
                        {
                            if (cGroup.myNeighbors.ContainsKey(cField))
                            {
                                if (!fullLib.ContainsKey(cField)) fullLib[cField] = cField;
                                if (fullLib.Count > morethan) break;
                            }
                            if (fullLib.Count > morethan) break;
                        }
                    }
                }
            }
            //if (theLibs.Count != getLibertyCount(thepos, theBoard) && theLibs.Count > morethan && getLibertyCount(thepos, theBoard) <= morethan)
            //{
            //    ;
            //}
            return fullLib.Count;
        }
        static public Dictionary<int, List<int>> theGroups = new Dictionary<int, List<int>>();
        static public Dictionary<int, int> theGroupStat = new Dictionary<int, int>();
        static public List<int> theMerge = new List<int>();
        
        internal void checkeyes_now(Board board)
        {
            if (mypotEye.Count > 0 && myEyes.Count > 0)
            {
                foreach (int pos in myEyes.Keys.ToList())
                {
                    if (mypotEye.ContainsKey(pos))
                    {
                        mypotEye.Remove(pos);
                    }
                }
            }
            foreach (int pos in mypotEye.Keys.ToList())
            {
                if (!board.ispotentialeye(pos))
                {
                    //Board.randmovescount++;
                }
            }
            if (mypotEye.Count == 0) return;

            theGroups.Clear();
            theGroupStat.Clear();
            buildPotEyeDict(board);
            aktStat(board);
            while (removeFromPotEyeDict(board))
            {

            }
            theMerge.Clear();
            foreach (int pos in theGroups.Keys)
            {
                List<int> theG = theGroups[pos];
                foreach (int g in theG)
                {
                    if (!board.myGroup[g].myEyes.ContainsKey(pos))
                    {
                        board.myGroup[g].myEyes[pos] = pos;
                        //Board.randmovescount++;
                        board.myGroup[g].mypotEye.Remove(pos);
                        if (this.myposition != g && !theMerge.Contains(g)) theMerge.Add(g);
                        if (board.myGroup[g].myEyes.Count > 1)
                        {
                            removeFromEmptyFields(pos, board);
                        }
                    }
                }
            }
            if (theMerge.Count > 0)
            {
                foreach (int pos in theMerge)
                {
                    merge(board.myGroup[pos], board);
                }
                checkeyes_now(board);
            }
        }

        private void aktStat(Board board)
        {
            theGroupStat.Clear();
            foreach (int pos in theGroups.Keys)
            {
                foreach (int g in theGroups[pos])
                {
                    if (!theGroupStat.ContainsKey(g))
                    {
                        theGroupStat[g] = 1;
                    }
                    else
                    {
                        ++theGroupStat[g];
                    }
                }
            }
        }

        private bool removeFromPotEyeDict(Board board)
        {
            int pos1 = -1;
            int g1 = -1;
            bool done = false;
            while (!done)
            {
                done = true;
                foreach (int pos in theGroups.Keys)
                {
                    List<int> theG = theGroups[pos];
                    if (theG.Count == 1)
                    {
                        continue;
                    }
                    foreach (int g in theG)
                    {
                        if (board.myGroup[g].myEyes.Count > 0) continue;
                        if (theGroupStat[g] < 2)
                        {
                            pos1 = pos;
                            g1 = g;
                            break;
                        }
                    }
                    if (pos1 > -1)
                    {
                        theGroups.Remove(pos1);
                        aktStat(board);
                        pos1 = -1;
                        done = false;
                        break;
                    }
                }
            }
            return false;
        }

        public void buildPotEyeDict(Board board)
        {
            if (theGroups.ContainsKey(this.myposition)) return;
            foreach (int pos in mypotEye.Keys)
            {
                foreach (int n in getNeighbors(pos, board.myboardsize).Keys)
                {
                    if (!theGroups.ContainsKey(pos))
                    {
                        theGroups[pos] = new List<int>();
                    }
                    if (!theGroups[pos].Contains(board.myGroupPosition[n]))
                    {
                        theGroups[pos].Add(board.myGroupPosition[n]);
                        if (board.myGroupPosition[n] != this.myposition)
                        {
                            board.myGroup[board.myGroupPosition[n]].buildPotEyeDict(board);
                        }
                    }
                }
            }
        }

        internal void checkeyes_new(Board board)
        {
            //if (mypotEye.Count > 0 && myEyes.Count > 0)
            //{
            //    foreach (int pos in myEyes.Keys)
            //    {
            //        if (mypotEye.ContainsKey(pos))
            //        {
            //            mypotEye.Remove(pos);
            //        }
            //    }
            //}
            foreach(int p in mypotEye.Keys.ToList())
            {
                if (check_pos_as_eye(p, board))
                {
                    //++Board.randmovescount;
                    myEyes[p] = p;
                    mypotEye.Remove(p);
                    foreach (int g in getNeighbors(p, board.myboardsize).Keys)
                    {
                        if (board.myGroupPosition[g] != this.myposition)
                        {
                            merge(board.myGroup[board.myGroupPosition[g]], board);
                            checkeyes_new(board);
                        }
                    }
                    if (myEyes.Count > 1)
                    {
                        removeFromEmptyFields(p, board);
                    }
                }
                else
                {
                    ;
                }
            }
        }

        private bool check_pos_as_eye(int p, Board board)
        {
            foreach(int g in getNeighbors(p, board.myboardsize).Keys)
            {
                if (board.myGroupPosition[g] == this.myposition) continue;
                if (board.myGroup[board.myGroupPosition[g]].myEyes.Count > 0 && this.myEyes.Count>0) continue;
                return false;
            }
            return true;
        }


        /// <summary>
        /// check eyes 
        /// </summary>
        /// <param name="board">checks all groups on the board</param>
        internal void checkeyes_old(Board board)
        {
            //return;
            //int previousEyes = myEyes.Count;
            eyecandidates.Clear();
            //if (myEyes.Count >= 2 || myFields.Count < 7) return;
            //List<int> temp;
            //if (isMerged)
            ////&& Tree.myRootBoard.mytoMove == color.white)
            //{
            //    temp = myLibs.Keys.ToList();
            //}
            //else
            //{
            //    temp = Group.getNeighbors(board.mymovehistory[board.mymovehistory.Count - 1], board.myboardsize).Keys.ToList();
            //}
            if (mypotEye.Count > 0 && myEyes.Count > 0)
            {
                foreach (int pos in myEyes.Keys)
                {
                    if (mypotEye.ContainsKey(pos))
                    {
                        mypotEye.Remove(pos);
                    }
                }
            }

            //foreach (int p in mypotEye.Keys)
            //{
            //    foreach (Group cGroup in board.myGroup.Values)
            //    {
            //        if (cGroup.myposition == this.myposition) continue;
            //        if (cGroup.mypotEye.ContainsKey(p) && cGroup.mypotEye.Count>1)
            //        {
            //            foreach(int q in cGroup.mypotEye.Keys)
            //            {
            //                if (p==q) continue;
            //                if (mypotEye.ContainsKey(q))
            //                {
            //                    ;
            //                }
            //            }
            //        }
            //    }
            //}
            foreach (int pos in mypotEye.Keys.ToList())
            {
                //if (myEyes.ContainsKey(pos))
                //{
                //    mypotEye.Remove(pos);
                //    continue;
                //}
                //if (isMerged || myLibs.ContainsKey(pos))
                //{
                bool isEye = true;
                foreach (int n in getNeighbors(pos, board.myboardsize).Keys)
                {
                    if (!board.myGroupPosition.ContainsKey(n) || board.myGroup[board.myGroupPosition[n]].myColor != myColor)
                    {
                        isEye = false;
                        eyecandidates.Remove(pos);
                        break;
                    }

                    if (board.myGroupPosition[n] != myposition)
                    {
                        //if (board.myGroup[board.myGroupPosition[n]].myEyes.Count > 0 && myEyes.Count > 0)
                        //{
                        //    // is eye for both groups
                        //    //myEyes[pos] = pos;
                        //    //board.myGroup[board.myGroupPosition[n]].myEyes[pos] = pos;
                        //    //removeFromEmptyFields(pos, board);
                        //    //break;
                        //}
                        //else
                        //{
                        if (!eyecandidates.ContainsKey(pos))
                        {
                            eyecandidates[pos] = board.myGroupPosition[n];
                        }
                        else
                        {
                            if (eyecandidates[pos] != board.myGroupPosition[n])
                            {
                                isEye = false;
                                eyecandidates.Remove(pos);
                                break;
                            }
                        }
                        //}
                    }
                }
                if (isEye)
                {
                    if (!eyecandidates.ContainsKey(pos))
                    {
                        if (myEyes.Count == 0)
                        {
                            myEyes[pos] = pos;
                            if (mypotEye.ContainsKey(pos)) mypotEye.Remove(pos);
                        }
                        else
                        {
                            //if (myEyes.Count == 1)
                            //{
                            //    removeFromEmptyFields(myEyes.ElementAt(0).Key, board);
                            //}
                            myEyes[pos] = pos;
                            //if (Tree.myRootBoard.myGame.myBoard.myGroup.ContainsKey(this.myposition))
                            //{
                            //    ;
                            //}
                            if (mypotEye.ContainsKey(pos)) mypotEye.Remove(pos);
                            removeFromEmptyFields(pos, board);
                        }
                    }

                }
                //}
            }
            if (eyecandidates.Count > 1)
            {
                List<int> theMerge = new List<int>();
                List<int> theGList = new List<int>();
                foreach (int c in eyecandidates.Keys)
                {
                    if (theGList.Contains(eyecandidates[c]))
                    {

                        foreach (int i in eyecandidates.Keys)
                        {
                            if (eyecandidates[i] == eyecandidates[c])
                            {
                                myEyes[i] = i;

                                if (mypotEye.ContainsKey(i)) mypotEye.Remove(i);
                                board.myGroup[eyecandidates[c]].myEyes[i] = i;
                                if (board.myGroup[eyecandidates[c]].mypotEye.ContainsKey(i)) board.myGroup[eyecandidates[c]].mypotEye.Remove(i);
                                if (!theMerge.Contains(eyecandidates[c]) && eyecandidates[c] != myposition)
                                {
                                    theMerge.Add(eyecandidates[c]);
                                }
                                removeFromEmptyFields(i, board);
                            }
                        }

                    }
                    else
                    {
                        theGList.Add(eyecandidates[c]);
                    }
                }
                if (theMerge.Count > 0)
                {
                    foreach (int pos in theMerge)
                    {
                        merge(board.myGroup[pos], board);
                    }
                    checkeyes_old(board);
                }
            }
            //checkeyes(board);
            //if (previousEyes< myEyes.Count)
            //{
            //    mergeonEyes(board);
            //}
            // check if all eyes in all groups are recognized
            //checkeyes_new(board);

        }
        /// <summary>
        /// check eyes 
        /// </summary>
        /// <param name="board">checks all groups on the board</param>
        internal void checkeyes(Board board)
        {
            //return;
            //int previousEyes = myEyes.Count;
            eyecandidates.Clear();
            //if (myEyes.Count >= 2 || myFields.Count < 7) return;
            //List<int> temp;
            //if (isMerged)
            ////&& Tree.myRootBoard.mytoMove == color.white)
            //{
            //    temp = myLibs.Keys.ToList();
            //}
            //else
            //{
            //    temp = Group.getNeighbors(board.mymovehistory[board.mymovehistory.Count - 1], board.myboardsize).Keys.ToList();
            //}
            if (mypotEye.Count > 0 && myEyes.Count > 0)
            {
                foreach (int pos in myEyes.Keys.ToList())
                {
                    if (mypotEye.ContainsKey(pos))
                    {
                        mypotEye.Remove(pos);
                    }
                }
            }

            foreach(int pos in mypotEye.Keys.ToList())
            {
                if (!board.ispotentialeye(pos))
                {
                    //Board.randmovescount++;
                }
            }

            //foreach (int p in mypotEye.Keys)
            //{
            //    foreach (Group cGroup in board.myGroup.Values)
            //    {
            //        if (cGroup.myposition == this.myposition) continue;
            //        if (cGroup.mypotEye.ContainsKey(p) && cGroup.mypotEye.Count>1)
            //        {
            //            foreach(int q in cGroup.mypotEye.Keys)
            //            {
            //                if (p==q) continue;
            //                if (mypotEye.ContainsKey(q))
            //                {
            //                    ;
            //                }
            //            }
            //        }
            //    }
            //}
            bool isEye = true;
            //foreach (int pos in mypotEye.Keys.ToList())
            //{
            //    //if (myEyes.ContainsKey(pos))
            //    //{
            //    //    mypotEye.Remove(pos);
            //    //    continue;
            //    //}
            //    //if (isMerged || myLibs.ContainsKey(pos))
            //    //{
            //    isEye = true;
            //    foreach (int n in getNeighbors(pos, board.myboardsize).Keys)
            //    {
            //        if (!board.myGroupPosition.ContainsKey(n) || board.myGroup[board.myGroupPosition[n]].myColor != myColor)
            //        {
            //            isEye = false;
            //            break;
            //        }

            //        if (board.myGroupPosition[n] != myposition)
            //        {
            //            //if (board.myGroup[board.myGroupPosition[n]].myEyes.Count > 0 && myEyes.Count > 0)
            //            //{
            //            //    // is eye for both groups
            //            //    //myEyes[pos] = pos;
            //            //    //board.myGroup[board.myGroupPosition[n]].myEyes[pos] = pos;
            //            //    //removeFromEmptyFields(pos, board);
            //            //    //break;
            //            //}
            //            //else
            //            //{
            //            isEye = false;
            //            //eyecandidates.Remove(pos);
            //            break;

            //        }
            //    }

            //    if (isEye)
            //    {
            //        //if (!eyecandidates.ContainsKey(pos))
            //        //{
            //        if (myEyes.Count == 0)
            //        {
            //            myEyes[pos] = pos;
            //            if (mypotEye.ContainsKey(pos)) mypotEye.Remove(pos);
            //        }
            //        else
            //        {
            //            //if (myEyes.Count == 1)
            //            //{
            //            //    removeFromEmptyFields(myEyes.ElementAt(0).Key, board);
            //            //}
            //            myEyes[pos] = pos;
            //            //if (Tree.myRootBoard.myGame.myBoard.myGroup.ContainsKey(this.myposition))
            //            //{
            //            //    ;
            //            //}
            //            if (mypotEye.ContainsKey(pos)) mypotEye.Remove(pos);
            //            removeFromEmptyFields(pos, board);
            //        }
            //        //}

            //    }
            //    //}

            //}
            if (mypotEye.Count + myEyes.Count > 0)
            {
                List<int> theMerge = new List<int>();
                Dictionary<int, bool> thenewEyes = new Dictionary<int, bool>();
                bool isonegroup = true;
                foreach (int pos in mypotEye.Keys.ToList())
                {
                    isonegroup = true;
                    isEye = true;
                    foreach (int n in getNeighbors(pos, board.myboardsize).Keys)
                    {
                        if (!board.myGroupPosition.ContainsKey(n) || board.myGroup[board.myGroupPosition[n]].myColor != myColor)
                        {
                            isEye = false;
                            break;
                        }
                        if (board.myGroupPosition[n] != myposition)
                        {
                            isonegroup = false;
                            if (board.myGroup[board.myGroupPosition[n]].mypotEye.Count + board.myGroup[board.myGroupPosition[n]].myEyes.Count > 1)
                            {
                                //if (board.myGroup[board.myGroupPosition[n]].myFields.Count > 1) continue;
                                if (board.myGroup[board.myGroupPosition[n]].myEyes.Count > 0) continue;
                                int poteye = 0;
                                foreach (int t in board.myGroup[board.myGroupPosition[n]].mypotEye.Keys)
                                {
                                    //if (!mypotEye.ContainsKey(t))
                                    //{
                                    //    isEye = false;
                                    //    break;
                                    //}
                                    if (mypotEye.ContainsKey(t))
                                    {
                                        ++poteye;
                                        if (poteye > 1)
                                        {
                                            break;
                                        }
                                    }
                                }
                                if (poteye<2)
                                {
                                    isEye = false;
                                    break;
                                }
                            }
                            else
                            {
                                isEye = false;
                                break;
                            }

                            //if (board.myGroup[board.myGroupPosition[n]].mypotEye.Count < 2 || board.myGroup[board.myGroupPosition[n]].myFields.Count == 1)
                            //{

                            //    isEye = false;
                            //    break;
                            //}
                        }
                    }
                    if (isEye)
                    {
                        thenewEyes[pos] = isonegroup;
                    }
                }
                foreach (int pos in thenewEyes.Keys)
                {
                    if (thenewEyes[pos] || thenewEyes.Count > 1)
                    {
                        myEyes[pos] = pos;
                        //++Board.randmovescount;
                        if (mypotEye.ContainsKey(pos)) mypotEye.Remove(pos);
                        foreach (int n in getNeighbors(pos, board.myboardsize).Keys)
                        {
                            if (board.myGroupPosition.ContainsKey(n) && board.myGroupPosition[n] != myposition)
                            {
                                if (board.myGroup[board.myGroupPosition[n]].mypotEye.ContainsKey(pos))
                                {
                                    board.myGroup[board.myGroupPosition[n]].mypotEye.Remove(pos);
                                }
                                board.myGroup[board.myGroupPosition[n]].myEyes[pos] = pos;
                                if (!theMerge.Contains(board.myGroupPosition[n]))
                                {
                                    theMerge.Add(board.myGroupPosition[n]);
                                }
                            }
                        }
                        if (myEyes.Count > 1)
                        {
                            removeFromEmptyFields(pos, board);
                        }
                    }
                }
                if (theMerge.Count > 0)
                {
                    foreach (int pos in theMerge)
                    {
                        merge(board.myGroup[pos], board);
                    }
                    checkeyes(board);
                }

            }
            //checkeyes_old(board);
        }
            //if (eyecandidates.Count > 1)
            //{
            //    List<int> theMerge = new List<int>();
            //    List<int> theGList = new List<int>();
            //    foreach (int c in eyecandidates.Keys)
            //    {
            //        if (theGList.Contains(eyecandidates[c]))
            //        {

            //            foreach (int i in eyecandidates.Keys)
            //            {
            //                if (eyecandidates[i] == eyecandidates[c])
            //                {
            //                    if (!myEyes.ContainsKey(i))
            //                    {
            //                        ;
            //                    }
            //                    myEyes[i] = i;

            //                    if (mypotEye.ContainsKey(i)) mypotEye.Remove(i);
            //                    board.myGroup[eyecandidates[c]].myEyes[i] = i;
            //                    if (board.myGroup[eyecandidates[c]].mypotEye.ContainsKey(i)) board.myGroup[eyecandidates[c]].mypotEye.Remove(i);
            //                    if (!theMerge.Contains(eyecandidates[c]) && eyecandidates[c] != myposition)
            //                    {
            //                        theMerge.Add(eyecandidates[c]);
            //                    }
            //                    removeFromEmptyFields(i, board);
            //                }
            //            }

            //        }
            //        else
            //        {
            //            theGList.Add(eyecandidates[c]);
            //        }
            //    }
                //if (theMerge.Count>0)
                //{
                //    foreach(int pos in theMerge)
                //    {
                //        merge(board.myGroup[pos],board);
                //    }
                //    checkeyes(board);
                //}
            //}
            //if (previousEyes< myEyes.Count)
            //{
            //    mergeonEyes(board);
            //}
            // check if all eyes in all groups are recognized
            //checkeyes_new(board);

   
        private void removeFromEmptyFields(int pos, Board board)
        {
            if (myEyes.Count > 1)
            {
                if (board.myEmptyFields.ContainsKey(pos)) board.myEmptyFields.Remove(pos);
                if (myEyes.Count == 2)
                {
                    if (board.myEmptyFields.ContainsKey(myEyes.FirstOrDefault().Key)) board.myEmptyFields.Remove(myEyes.ElementAt(0).Key);
                }
                foreach (int lib in myLibs.Keys)
                {
                    bool skipit = false;
                    if (myEyes.ContainsKey(lib)) continue;
                    foreach (int nei in getNeighbors(lib, board.myboardsize).Keys)
                    {
                        if (myFields.ContainsKey(nei)) continue;
                        if (board.myGroupPosition.ContainsKey(nei))
                        {
                            if (board.myGroup[board.myGroupPosition[nei]].myEyes.Count < 2 || board.myGroup[board.myGroupPosition[nei]].myColor != myColor)
                            {
                                skipit = true;
                                break;
                            }
                        }
                    }

                    if (!skipit && !myEyes.ContainsKey(lib))
                    {
                        eyes = new List<int>();
                        getFieldsOfMyAliveGroups(lib, board, true);
                        if (eyes != null)
                        {
                            foreach (int t in eyes)
                            {
                                myEyes[t] = t;
                                board.myEmptyFields.Remove(t);
                            }
                            
                        }
                    }
                }
            }
        }

        //private void mergeonEyes(Board board)
        //{
        //    foreach (int t in myEyes.Keys.ToList())
        //    {
        //        foreach (int nei in getNeighbors(t, board.myboardsize).Keys)
        //        {
        //            if (board.myGroupPosition.ContainsKey(nei))
        //            {
        //                if (board.myGroupPosition[nei] != myposition)
        //                {
        //                    merge(board.myGroup[board.myGroupPosition[nei]], board);
        //                }
        //            }
        //        }
        //    }
        //}

        public static List<int> eyes;
        public void getFieldsOfMyAliveGroups(int lib, Board board, bool eyesNeeded)
        {
            if (eyes.Count > 7)
            {
                eyes = null;
                return;
            }
            eyes.Add(lib);
            foreach (int nei in getNeighbors(lib, board.myboardsize).Keys)
            {
                if (board.myGroupPosition.ContainsKey(nei))
                {

                    if ((eyesNeeded && board.myGroup[board.myGroupPosition[nei]].myEyes.Count < 2)  || board.myGroup[board.myGroupPosition[nei]].myColor != myColor)
                    {
                        eyes = null;
                        return;
                    }
                    if (!eyesNeeded && board.myGroup[board.myGroupPosition[nei]].myEyes.Count > 0)
                    {
                        eyes = null;
                        return;
                    }
                }
                else
                {
                    if (eyes.Contains(nei)) continue;
                    getFieldsOfMyAliveGroups(nei, board, eyesNeeded);
                    if (eyes == null) return;
                }
            }
            
        }
        /// <summary>
        /// check alive vs. dead for all groups
        /// </summary>
        /// <param name="Board"></param>
        internal static void aliveCount(Board theBoard, Board theResultBoard)
        {
            foreach (Group cGroup in theBoard.myGroup.Values)
            {
                cGroup.checkAlive(theResultBoard);
            }
        }
        /// <summary>
        /// check alive vs. dead
        /// </summary>
        /// <param name="theBoard"></param>
        private void checkAlive(Board theResultBoard)
        {
            bool isdead = false;
            foreach (int pos in myFields.Keys)
            {
                if (theResultBoard.myGroupPosition.ContainsKey(pos))
                {
                    if (theResultBoard.myGroup[theResultBoard.myGroupPosition[pos]].myColor != myColor)
                    {
                        isdead = true;
                        break;
                    }
                }
                else
                {
                    isdead = true;
                    break;
                }
            }
            if (isdead)
            {
                ++dead;
            }
            else
            {
                ++alive;
            }
        }
    }
}
